package taskexecutor

import (
	"context"
	"fmt"
	"log"
	"main/handlers"
	"strconv"
	"strings"
	"sync"
	"time"
)

// Task 代表一个计划任务
type Task struct {
	ID                           int64
	AlarmConfigName              string
	AlarmConfigGroupCronSchedule string // 存储 "分 时 日 月 周"
	AlarmConfigGroupCode         string
	AlarmConfigGroupUrl          string
	AlarmConfigFormula           string
	AlarmCorrectValue            string
	AlarmJudgmentFormula         string
	AlarmConfigAction            string
	AlarmConfigGroupToken        string
}

// TaskExecutor 负责管理计划任务
type TaskExecutor struct {
	Ticker       *time.Ticker
	Ctx          context.Context
	Cancel       context.CancelFunc
	ExecutingMap sync.Map      // 用于记录当前正在执行的任务组
	Semaphore    chan struct{} // 信号量，用于限制并发任务数量
}

// NewTaskExecutor 创建新的任务执行器
func NewTaskExecutor(tickInterval time.Duration, maxConcurrentTasks int) *TaskExecutor {
	ctx, cancel := context.WithCancel(context.Background())
	return &TaskExecutor{
		Ticker:    time.NewTicker(tickInterval),
		Ctx:       ctx,
		Cancel:    cancel,
		Semaphore: make(chan struct{}, maxConcurrentTasks), // 限制并发任务数
	}
}

// FetchTasks 从数据库中获取任务并按 alarm_config_group_id 分组
func (te *TaskExecutor) FetchTasks() ([][]Task, error) {
	tasksData, err := handlers.ExecuteQuery(`  
	SELECT * FROM alarm_config_group a  
	LEFT JOIN alarm_config b ON a.alarm_config_group_id = b.alarm_config_group_id  
	WHERE b.alarm_status = 1
	AND b.alarm_config_del != 1`)

	if err != nil {
		log.Printf("Error executing query: %v", err)
		return nil, err
	}

	// 使用一个字典来存储按 alarm_config_group_id 分组的任务
	groupedTasks := make(map[int64][]Task)

	for _, taskMap := range tasksData {
		id, _ := taskMap["alarm_config_id"].(int64)
		alarmConfigGroupID, _ := taskMap["alarm_config_group_id"].(int64)

		alarmConfigName, _ := taskMap["alarm_config_name"].(string)
		schedule, _ := taskMap["alarm_config_group_cron_schedule"].(string)
		alarmConfigGroupCode, _ := taskMap["alarm_config_group_code"].(string)
		alarmConfigGroupUrl, _ := taskMap["alarm_config_group_url"].(string)
		alarmConfigFormula, _ := taskMap["alarm_config_formula"].(string)
		alarmCorrectValue, _ := taskMap["alarm_correct_value"].(string)
		alarmJudgmentFormula, _ := taskMap["alarm_judgment_formula"].(string)
		alarmConfigAction, _ := taskMap["alarm_config_action"].(string)
		alarmConfigGroupToken, _ := taskMap["alarm_config_group_token"].(string)

		task := Task{
			ID:                           id,
			AlarmConfigName:              alarmConfigName,
			AlarmConfigGroupCronSchedule: schedule,
			AlarmConfigGroupCode:         alarmConfigGroupCode,
			AlarmConfigGroupUrl:          alarmConfigGroupUrl,
			AlarmConfigFormula:           alarmConfigFormula,
			AlarmCorrectValue:            alarmCorrectValue,
			AlarmJudgmentFormula:         alarmJudgmentFormula,
			AlarmConfigAction:            alarmConfigAction,
			AlarmConfigGroupToken:        alarmConfigGroupToken,
		}

		// 根据 alarm_config_group_id 分组任务
		groupedTasks[alarmConfigGroupID] = append(groupedTasks[alarmConfigGroupID], task)
	}

	// 将分组的任务转换为二维切片
	result := make([][]Task, 0, len(groupedTasks))
	for _, group := range groupedTasks {
		result = append(result, group)
	}

	return result, nil
}

// filterExecutableTasks 筛选当前时间需要执行的任务
func filterExecutableTasks(tasks []Task, currentTime time.Time) []Task {
	executableTasks := []Task{}
	for _, task := range tasks {
		if task.ShouldExecute(currentTime) {
			executableTasks = append(executableTasks, task)
		}
	}
	return executableTasks
}

// ShouldExecute 判断任务是否应在当前时间执行
func (t Task) ShouldExecute(currentTime time.Time) bool {
	scheduleParts := strings.Split(t.AlarmConfigGroupCronSchedule, " ")
	if len(scheduleParts) != 5 {
		log.Printf("Invalid schedule format for task %d: %s", t.ID, t.AlarmConfigGroupCronSchedule)
		return false
	}

	return matchesCronField(scheduleParts[0], currentTime.Minute()) &&
		matchesCronField(scheduleParts[1], currentTime.Hour()) &&
		matchesCronField(scheduleParts[2], currentTime.Day()) &&
		matchesCronField(scheduleParts[3], int(currentTime.Month())) &&
		matchesCronField(scheduleParts[4], int(currentTime.Weekday()))
}

// matchesCronField 检查当前值是否匹配 cron 字段
func matchesCronField(field string, currentValue int) bool {
	values := strings.Split(field, ",")
	for _, value := range values {
		if value == "*" || value == fmt.Sprint(currentValue) {
			return true
		}

		// 支持 */n 的格式
		if strings.HasPrefix(value, "*/") {
			interval, err := strconv.Atoi(value[2:])
			if err != nil {
				log.Printf("Invalid interval in cron field: %s", value)
				continue
			}
			if currentValue%interval == 0 {
				return true
			}
		} else if strings.Contains(value, "-") {
			rangeParts := strings.Split(value, "-")
			if len(rangeParts) != 2 {
				log.Printf("Invalid range in cron field: %s", value)
				continue
			}
			start, err1 := strconv.Atoi(rangeParts[0])
			end, err2 := strconv.Atoi(rangeParts[1])
			if err1 == nil && err2 == nil && currentValue >= start && currentValue <= end {
				return true
			}
		} else {
			val, err := strconv.Atoi(value)
			if err == nil && val == currentValue {
				return true
			}
		}
	}
	return false
}

// Start 启动任务执行器
func (te *TaskExecutor) Start() {
	go func() {
		for {
			select {
			case <-te.Ticker.C:
				currentTime := time.Now()

				// 获取分组任务
				taskGroups, err := te.FetchTasks()
				if err != nil {
					log.Println("Error fetching tasks:", err)
					continue
				}

				for _, taskGroup := range taskGroups {
					groupID := taskGroup[0].ID // 假设任务组内任务具有相同的 ID

					// 如果当前任务组正在执行，跳过该组
					if _, isExecuting := te.ExecutingMap.Load(groupID); isExecuting {
						log.Printf("Task group %d is already executing, skipping...", groupID)
						continue
					}

					// 筛选符合条件的任务
					executableTasks := filterExecutableTasks(taskGroup, currentTime)
					if len(executableTasks) > 0 {
						// 标记任务组为执行中
						te.ExecutingMap.Store(groupID, struct{}{})

						// 启动任务组执行协程
						go func(tasks []Task, groupID int64) {
							defer te.ExecutingMap.Delete(groupID) // 任务完成后解除标记

							// 使用信号量限制并发数
							select {
							case te.Semaphore <- struct{}{}: // 尝试占用信号量
								defer func() { <-te.Semaphore }() // 释放信号量
								te.ExecuteTask(tasks)             // 执行任务组
							default:
								// 信号量满时记录日志
								log.Printf("Task group %d is waiting to execute (queued). Current pending tasks: %d",
									groupID, len(te.Semaphore))
							}
						}(executableTasks, groupID)
					}
				}

				// 记录当前堆积任务数（信号量的长度）
				pendingTasks := cap(te.Semaphore) - len(te.Semaphore)
				log.Printf("当前队列空闲: %d (最大执行队列: %d)", pendingTasks, cap(te.Semaphore))

			case <-te.Ctx.Done():
				te.Ticker.Stop()
				return
			}
		}
	}()
}

// Stop 停止任务执行器
func (te *TaskExecutor) Stop() {
	te.Cancel()
	log.Println("TaskExecutor stopped.")
}
